// +build linux

package main

/*
#cgo CFLAGS: -I${SRCDIR}/../../2nd/cryptogo/include
#cgo LDFLAGS: -L${SRCDIR}/../../2nd/cryptogo/lib/Linux_x86_64 -L${SRCDIR}/../../3rd/openssl-OpenSSL_1_0_2-stable/lib/Linux_x86_64 -lmism -lssl -lcrypto -lstdc++ -ldl
#include "ISafeInterface.h"
*/
import "C"
import (
	"fmt"
	"unsafe"
)

// GetSafeHandle 获取对象.
func GetSafeHandle() unsafe.Pointer {
	h := C.MIGetSafeHandle()
	C.MILoad(nil, C.int(0), h)
	return unsafe.Pointer(&h)
}

// FreeSafeHandle 释放.
func FreeSafeHandle(h unsafe.Pointer) {
	lh := C.long(*(*int64)(h))
	C.MIFreeSafeHandle(lh)
}

// TransEncrypt 加密.
func TransEncrypt(h unsafe.Pointer, src []byte) []byte {
	var iLen int32
	var srcLen int = len(src)
	lh := C.long(*(*int64)(h))
	C.MIGetEncryptDataLen((*C.int)(&iLen), (*C.char)(unsafe.Pointer(&src[0])), C.int(srcLen), lh)
	buf := make([]byte, iLen)
	C.MITransEncrypt((*C.char)(unsafe.Pointer(&buf[0])), C.int(iLen), (*C.char)(unsafe.Pointer(&src[0])), C.int(srcLen), lh)

	return buf
}

// TransDecrypt 解密.
func TransDecrypt(h unsafe.Pointer, src []byte) ([]byte, error) {
	dstLen := len(src)
	var iDLen int32
	lh := C.long(*(*int64)(h))
	C.MIGetDecryptDataLen((*C.int)(&iDLen), (*C.char)(unsafe.Pointer(&src[0])), C.int(dstLen), lh)
	if iDLen > 100000 || iDLen < 0 {
		return nil, fmt.Errorf("get descrypt datalen too long: %d", iDLen)
	}
	newSrc := make([]byte, iDLen)
	r1 := C.MITransDecrypt((*C.char)(unsafe.Pointer(&newSrc[0])), C.int(iDLen), (*C.char)(unsafe.Pointer(&src[0])), C.int(dstLen), lh)
	var err error = nil
	if int(r1) != 0 {
		err = fmt.Errorf("MITransDecrypt fail, iLen:%d ret:%d", iDLen, int(r1))
	}

	return newSrc, err
}
